﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace WindowsUserControl.Dialogs
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="assemblyFilePath"></param>
    /// <param name="typeFullName"></param>
    public delegate void ClassSelected(string assemblyFilePath, string typeFullName);

    /// <summary>
    /// 
    /// </summary>
    public partial class ClassBrowser : Form
    {
        /// <summary>
        /// 
        /// </summary>
        public event ClassSelected OnClassSelected;

        private readonly Type _InterfaceType;
        private Assembly _Assembly;
        private string _TypeFullName;

        /// <summary></summary>
        public ClassBrowser()
        {
            InitializeComponent();
        }
        /// <summary></summary>
        public ClassBrowser(Assembly assembly, Type interfaceType)
        {
            InitializeComponent();
            this._Assembly = assembly;
            this._InterfaceType = interfaceType;
        }

        private void ClassBrowser_Load(object sender, EventArgs e)
        {
            if (this._Assembly == null)
            {
                if(this.ParentForm !=null)
                {
                    this._Assembly = this.ParentForm.GetType().Assembly;
                }
                else
                {
                    this._Assembly = sender.GetType().Assembly;
                }
            }
            this.txt_AssemblyFilePath.Text = this._Assembly.GetName().Name;
            if(this._InterfaceType !=null)
            {
                this.lbl_InterfaceName.Text = this._InterfaceType.Name;
            }
            this.PopulateClasses(this._Assembly,this._InterfaceType);
            if (this.cbo_Classes.Items.Count > 0 && (!string.IsNullOrEmpty(this._TypeFullName)))
            {
                for (int i = 0; i < this.cbo_Classes.Items.Count; i++)
                {
                    if (this.cbo_Classes.Items[i].ToString() == this._TypeFullName)
                    {
                        this.cbo_Classes.SelectedIndex = i;
                        break;
                    }
                }
            }
        }

        private void btn_Browse_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg=new OpenFileDialog();
            dlg.Filter = "Assemblies(*.dll)|*.dll";
            if(dlg.ShowDialog()==System.Windows.Forms.DialogResult.OK)
            {
                this.txt_AssemblyFilePath.Text = dlg.FileName;
                this._Assembly = Assembly.LoadFile(this.txt_AssemblyFilePath.Text);
                this.PopulateClasses(this._Assembly, this._InterfaceType);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblyFilePath"></param>
        /// <param name="typeFullName"></param>
        public void UpdateDisplay(string assemblyFilePath, string typeFullName)
        {
            if (File.Exists(assemblyFilePath))
            {
                this._Assembly = Assembly.LoadFile(assemblyFilePath);
            }
            this._TypeFullName = typeFullName;
            
        }

        private void PopulateClasses(Assembly assembly, Type interfaceType)
        {
            this.cbo_Classes.Items.Clear();
            this.cbo_Classes.SelectedIndex = -1;
            this.cbo_Classes.Text = string.Empty;

            Type[] types = assembly.GetTypes();
            foreach(Type type in types)
            {
                bool add = true;
                if(interfaceType !=null)
                {
                    if(type.GetInterface(interfaceType.Name)==null)
                    {
                        add = false;
                    }
                }
                if(add)
                {
                    this.cbo_Classes.Items.Add(type.FullName);
                }
            }
        }

        private void btn_OK_Click(object sender, EventArgs e)
        {
            if(this.cbo_Classes.SelectedIndex >=0 && this._Assembly !=null)
            {
                if(this.OnClassSelected !=null)
                {
                    this.OnClassSelected(this._Assembly.Location, this.cbo_Classes.Text);
                }
            }
            this.Close();
        }

        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
